home *** CD-ROM | disk | FTP | other *** search
- name msxv90
- ; File MSXV90.ASM
- include mssdef.h
- ; Copyright (C) 1982,1991, Trustees of Columbia University in the
- ; City of New York. Permission is granted to any individual or
- ; institution to use, copy, or redistribute this software as long as
- ; it is not sold for profit and this copyright notice is retained.
- ; Kermit system dependent module for VICTOR 9000/SIRIUS
- ; Edit History
- ; 2 March 1991 version 3.10
- ; Last edit: 17 Dec 1990 MS-DOS Kermit v3.02 editing. [jrd]
- ; 12 June 1988 Add error recovery if serial port fails to initialize. [jrd]
- ; 9 March 1988 Add procedure getmodem and global byte mdmhand for use by
- ; scripts in sensing modem status. Add: ignore received XOFF if we have sent
- ; an XOFF already (avoids lockouts from echoes). Add user/buffer xon/xoff
- ; sensing. [jrd]
- ; 3 March 1988 Add shomodem routine to show status of DSR, CD, CTS lines
- ; [bgp]
- ; 7 Sept 1987 Remove keep_delete, pass null, del chars to terminal section.
- ; [jrd]
- ; 29 August 1987 Add capability for sending long break [bgp]
- ; 9 February 1987 Add flag for ignoring delete chars in SERINT - they must
- ; be retained when emulating a Tektronix (graphics mode) - this is done
- ; using global symbol keep_delete.
- ; 6 November 1986 Fix receiver overrun detection and miscellaneous minor
- ; fixes
- ; 30 Sept 1986 Reject DEL char at serial port reception level to avoid
- ; problems when DEL is used as a filler char (be Emacs). [jrd]
- ; 16 Sept 1986 Revise serial port routines prtchr, outchr, serini, serint
- ; to use more efficient code from IBM version. [jrd]
- ; 4 Sept 1986 Add Bob Goeke's change to move comms port table to a system
- ; dependent module (typ msx---) to allow 3+ ports and localized idents. [jrd]
- ; 26 August 1986 Use parity mask when testing for nulls & Xon/Xoff in serial
- ; port interrupt routine. [jrd]
- ; 16 August 1986 Use observed screen attributes for mode line. [jrd]
- ; 9 August 1986 Revise SERINT to insert control-G for overrun chars, give
- ; faster return of interrupts to system, remove use of BP in code. [jrd]
- ; Original version, BGP, 23 November 1985
- ; Add global entry point vtstat for use by Status routine in mssset.
- ; Cleared terminal emulation flag, flags.vtflg, in procedure lclini.
- ; Add register save/restore in procedure getbaud.
- ; Joe R. Doupnik 12 March 1986
- ; Add some register save/restores here and there.
- ; Add global procedures ihosts and ihostr to handle host initialization
- ; when packets are to be sent or received by us,resp. 24 March 1986
- ; Add global procedure dtrlow to force DTR and RTS low in support of Kermit
- ; command Hangup. B.G.Peterson 10 April 1986
- ; Add support of serial port settings through use of IOCTL DOS function
- ; code from Andreas Stumpf (ZRZS@DS0RUS1I), merged by B.G.Peterson 10 April 86
- ; Moved VTS and VTSTAT routines to MSYxxx.ASM where the terminal emulation
- ; is done anyway. B.G.Peterson 10 April 1986
- ; Last update 28 April 1986
- ; 30 July 1986 Corrected IHOSTS and IHOSTR to prevent sending null byte if
- ; no flow control.
- ; Modified SERHNG so it turns DTR and RTS off for 3 seconds and then back
- ; on again so a new connection can be made easily.
- ; Modified SERRST to wait until transmitter is empty before turning off
- ; port.
- ; Modified port controller access so that if opening it using the standard
- ; Victor drivers fails, it will just go direct to the hardware. [bgp]
-
- public serini, serrst, clrbuf, outchr, coms, dodel
- public ctlu, cmblnk, locate, lclini, prtchr, dobaud
- public clearl, getbaud, beep, puthlp, putmod
- public clrmod, poscur, sendbr, showkey, sendbl, pcwait
- public xofsnt, machnam, setktab, setkhlp, count
- public ihosts, ihostr, dtrlow, comptab, serhng, mdmhand
- public shomodem, getmodem, baudst, bdtab, portval
- public parmsk, flowon, flowoff, peekcom
-
- FALSE equ 0
- off equ 0
- bufon equ 1 ; buffer level xon/xoff on-state control flag
- usron equ 2 ; user level xon/xoff on-state control flag
- MNTRGH EQU BUFSIZ*3/4 ; High point = 3/4 of buffer full.
- MNTRGL EQU BUFSIZ/4 ; Low point = 1/4 of buffer full.
- DEF_BAUD EQU 8 ; Default to 1200 baud
-
- ; constants used by serial port handler
-
- SEG_7201 EQU 0E004H ; Segment for 7201 serial controller
- DATAA_7201 EQU 0 ; DATA A offset
- STATA_7201 EQU 2 ; STATUS A offset
- DATAB_7201 EQU 1 ; DATA B offset
- STATB_7201 EQU 3 ; STATUS B offset
-
- ; no interrupts, no waits
- REG1_7201 EQU 0 ; 7201 Register 1 value
- ENABLE_INT EQU 18H ; Mask to turn on interrupts (OR)
- ; non-DMA, non-vectored interrupts, priority type 1 (Ra>Rb>Ta>Tb)
- REG2_7201 EQU 14H ; 7201 Register 2 value
- ; 8 bits/char, no CRC, receiver enabled
- REG3_7201 EQU 0C1H ; 7201 Register 3 value
- ; clock/16, 1.5 stop bit, no parity
- REG4_7201 EQU 48H ; 7201 Register 4 value
- ; DTR low (active), 8 bits/char, transmitter enabled, RTS low, no CRC
- REG5_7201 EQU 0EAH ; 7201 Register 5 value
- BREAK_ON EQU 10H ; Mask to turn on break bit (OR)
- DTR_RTS_OFF EQU 7DH ; Mask to turn off DTR and RTS (AND)
-
- MDMINP EQU 1 ; Input ready bit. [jrd]
- MDMOVER EQU 32 ; Receiver overrun bit. [bgp]
-
- SEG_8253 EQU 0E002H ; Segment for 8253 timer
- SETA_8253 EQU 0 ; Speed for port A
- SETB_8253 EQU 1 ; Speed for port B
- CTRL_8253 EQU 3 ; Control for 8253 timer
-
- SEG_8259 EQU 0E000H ; Segment for 8259 int. controller
- CW1_8259 EQU 0 ; Offset for 8259 register 1
- CW2_8259 EQU 1 ; Offset for 8259 register 2
-
- ; external variables used:
- ; drives - # of disk drives on system
- ; flags - global flags as per flginfo structure defined in pcdefs
- ; trans - global transmission parameters, trinfo struct defined in pcdefs
- ; portval - pointer to current portinfo structure (currently either port1
- ; or port2)
- ; port1, port2 - portinfo structures for the corresponding ports
-
- ; global variables defined in this module:
- ; xofsnt, xofrcv - tell whether we saw or sent an xoff.
- ; setktab - keyword table for redefining keys (should contain a 0 if
- ; not implemented)
- ; setkhlp - help for setktab.
-
- data segment
- extrn flags:byte, trans:byte
-
- setktab db 0
- setkhlp db CR,LF,'Set Key not supported on VICTOR/SIRIUS Kermit$'
- sh_key_str db 'Set Key not supported on VICTOR/SIRIUS Kermit'
- sh_key_len dw 45
- machnam db 'VICTOR/SIRIUS$'
- clrlin db CR ; clears full line with next line...
- clreol db ESCAPE,'K$' ; clears from cursor to end of line
- home db ESCAPE,'H$' ; homes cursor
- clrscr db ESCAPE,'E$' ; clears screen and homes cursor
- delstr db BS,BS,' ',BS,BS,'$' ; Delete string
- clr_25 db ESCAPE,'j',ESCAPE,'x1',ESCAPE,'Y8 ',ESCAPE,'l',ESCAPE,'k'
- db ESCAPE,'y1$'
- ;clr_25 does the entire operation of clearing the mode line
- start_25 db ESCAPE,'j',ESCAPE,'x1',ESCAPE,'Y8 ',ESCAPE,'p$'
- ; start_25 enables line 25 and moves to the start in reverse video
- end_25 db ESCAPE,'q',ESCAPE,'k',ESCAPE,'y1$'
- ; end_25 turns off reverse video and line 25 and returns the cursor
- mov_pfx db ESCAPE,'Y$' ; prefix for moves
- mdminfo struc
- mddat dw 0 ; data register
- mdiir dw 0 ; interrupt identification register
- mdstat dw 0 ; line status register
- mdcom dw 0
- mden db 0
- mddis db 0
- mdmeoi db 0
- mdintv dw 0
- mdminfo ends
- modem mdminfo <DATAA_7201,0,STATA_7201,SETA_8253,0FDH,2,61H,104H>
- port1 prtinfo <0FFFH,0,defpar,1,0,defhand,floxon,0> ; UART ports
- port2 prtinfo <0FFFH,0,defpar,1,0,defhand,floxon,0>
- portval dw port1 ; Default is to use port 1
- savsci dw ? ; Save for serial port interrupt vector.
- savscs dw ? ; Ditto.
- portin db FALSE ; Has comm port been initialized.
- xofsnt db FALSE ; Say if we sent an XOFF.
- xofrcv db FALSE ; Say if we received an XOFF.
- parmsk db ? ; parity mask, 0ffh for no parity, 07fh with.
- flowoff db ? ; flow-off char, Xoff or null (if no flow)
- flowon db ? ; flow-on char, Xon or null
- overrun db ? ; holds status of receiver overrun
- mdmhand db 0 ; Modem status register, current.
- erms20 db CR,LF,'?Warning: System has no disk drives$'
- badbd db CR,LF,'Unimplemented baud rate$'
- hngmsg db CR,LF,' The phone should have hung up.',CR,LF,'$' ; [jrd]
- hnghlp db CR,LF,' The modem control lines DTR and RTS for the current'
- db ' port are forced low (off)'
- db CR,LF,' to hang up the phone. Normally, Kermit leaves them'
- db ' high (on) when it exits.'
- db CR,LF,' They will return high after about 3 seconds.'
- db CR,LF,'$' ; [jrd]
- shmdm0 db CR,LF,' Modem is not ready: DSR is off$'
- shmdm1 db CR,LF,' Modem is ready: DSR is on$' ; [bgp]
- shmdm2 db CR,LF,' no Carrier Detect: CD is off$'
- shmdm3 db CR,LF,' Carrier Detect: CD is on$'
- shmdm4 db CR,LF,' no Clear to Send: CTS is off$'
- shmdm5 db CR,LF,' Clear to Send: CTS is on$' ; [bgp]
- tmp db ?,'$'
- temp1 dw ? ; Temporary storage.
-
- ontab db 02H ; Two entries.
- mkeyw 'OFF',00H
- mkeyw 'ON',01H
-
- comptab db 0AH
- mkeyw '1',01H
- mkeyw '2',00H
- mkeyw 'A',01H
- mkeyw 'B',00H
- mkeyw 'COM1',01H
- mkeyw 'COM2',00H
- mkeyw 'SERIALA',01H
- mkeyw 'SERIALB',00H
- mkeyw 'TTY',01H
- mkeyw 'UL1',00H
-
- bdtab db 16 ; Baud rate table
- mkeyw '45.5',0
- mkeyw '50',1
- mkeyw '75',2
- mkeyw '110',3
- mkeyw '134.5',4
- mkeyw '150',5
- mkeyw '300',6
- mkeyw '600',7
- mkeyw '1200',8
- mkeyw '1800',9
- mkeyw '2000',10
- mkeyw '2400',11
- mkeyw '4800',12
- mkeyw '9600',13
- mkeyw '19200',14
- mkeyw '38400',15
-
- ; This table is indexed by the baud rate definitions given above.
- ; Unsupported baud rates should contain FF.
- ; This number is determined by 78125/(baud rate) (decimal values)
-
- bddat label word
- dw 6B4H ; 45.5 baud
- dw 61AH ; 50 baud
- dw 411H ; 75 baud
- dw 2C6H ; 110 baud
- dw 244H ; 134.5 baud
- dw 208H ; 150 baud
- dw 104H ; 300 baud
- dw 82H ; 600 baud
- dw 41H ; 1200 baud
- dw 2BH ; 1800 baud
- dw 26H ; 2000 baud
- dw 20H ; 2400 baud
- dw 10H ; 4800 baud
- dw 8H ; 9600 baud
- dw 4H ; 19200 baud
- dw 2H ; 38400 baud
-
- ; variables for serial interrupt handler
-
- source db BUFSIZ DUP(?) ; Buffer for data from port.
- srcpnt dw 0 ; Pointer in buffer (DI).
- count dw 0 ; Number of chars in int buffer.
-
- ; variables for accessing portinfo from serial drivers using IOCTL function
- ;
- ; Structure is defined according to "Systems Programmers Toolkit II",
- ; Appendix A. Structure contains baud rate and values of control registers
- ; 0 through 7.
-
- pval struc
- stype dw 11H ; port access
- status dw (?)
- blocktype dw 0 ; serial
- baudr dw (?) ; baud rate to set or get
- CR0 db (?)
- CR1 db (?)
- CR2A db (?)
- CR2B db (?)
- CR3 db (?)
- CR4 db (?)
- CR5 db (?)
- CR6 db (?)
- CR7 db (?)
- pval ends
-
- erms41 db CR,LF,'?Warning: Cannot open com port'
- db CR,LF,' Going direct to serial controller hardware...$' ; [bgp]
- rdbuf db 20 dup (?) ; input buffer
-
- plength equ 17 ; length of pval structure
- oldpval pval <,,,41H,,,,,,,,,> ; default to 1200 baud
- newpval pval <,,,41H,,,,,,,,,> ; value comes from bdtab above... [bgp]
-
- prttab dw com2,com1 ; 0=com2, 1=com1 in flags.comflg
- com1 db 'SERIALA',0 ; name string for device
- com2 db 'SERIALB',0
-
- IOread equ 2 ; read status block
- IOwrite equ 3 ; write status block
-
- prthnd dw 0 ; handle for accessing port
-
- data ends
-
- code segment
- extrn comnd:near, dopar:near, defkey:near
- extrn lclyini:near
- assume cs:code,ds:data,es:nothing
-
- ; local initialization
-
- LCLINI proc near
- mov flags.vtflg,TTHEATH ; BIOS does HEATH, use as default
- cmp flags.comflg,1 ; using port 1?
- jne lclini2 ; no...
- mov portval,offset port1
- mov modem.mddat,DATAA_7201 ; set COM1 values
- mov modem.mdstat,STATA_7201
- mov modem.mdcom,SETA_8253
- jmp lclini0
- lclini2: ; using port2
- mov portval,offset port2
- mov modem.mddat,DATAB_7201 ; set COM2 values
- mov modem.mdstat,STATB_7201
- mov modem.mdcom,SETB_8253
- lclini0:call opnprt ; get file handle and init port
- call lclyini ; init term part too
- ret
- LCLINI endp
-
- ; procedure to get a file handle for the port. if it fails ask the user
- ; for some predefined handle (3 is the usual value) (Andreas Stumpf)
- ; 30 July 1986 If it fails, just warn the user and go direct to the
- ; hardware [bgp]
-
- OPNPRT proc near
- cmp prthnd,0 ; is one open?
- jle opnprta ; no...
- mov bx,prthnd ; better close this
- mov ah,CLOSE2 ; to be sure they don't accumulate
- int DOS
- mov prthnd,0 ; done...
- opnprta:
- mov al,flags.comflg
- mov ah,0
- mov si,ax
- shl si,1 ; double index
- mov dx,prttab[si]
- mov ah,OPEN2
- mov al,2
- int DOS ; open port on handle
- jnc opnprt2
- mov ah,PRSTR ; it didn't like the string...
- mov dx,offset erms41
- int DOS
- mov prthnd,-1 ; no port is open! [bgp]
- push es ; better save this
- mov bx,SEG_7201 ; point at controller
- mov es,bx
- mov bx,modem.mdstat
- mov byte ptr es:[bx],1
- mov byte ptr es:[bx],18H ; Software reset of current port
- push ax ; kill time for four 2.5 MHz cylces
- pop ax ; 8 processor cycles
- mov bx,STATA_7201 ; First one is always port A
- mov byte ptr es:[bx],2 ; must be first one set
- mov byte ptr es:[bx],REG2_7201
- mov bx,modem.mdstat
- mov byte ptr es:[bx],4 ; must be second
- mov byte ptr es:[bx],REG4_7201
- mov byte ptr es:[bx],1 ; rest any order
- mov byte ptr es:[bx],REG1_7201
- mov byte ptr es:[bx],3
- mov byte ptr es:[bx],REG3_7201
- mov byte ptr es:[bx],5
- mov byte ptr es:[bx],REG5_7201
- pop es
- call getbaud ; use this to be sure right value is used
- call dobaud ; better set baud rate to the correct value too
- jmp opnprt2a ; all init done... [bgp]
- opnprt2:
- mov prthnd,ax ; call succeeded - save handle
- mov bx,ax
- mov ah,IOCTL
- mov al,IOread ; get old values
- mov cx,plength
- mov dx,offset oldpval ; place for old values
- int DOS
- mov ah,IOCTL
- mov al,IOread
- mov dx,offset newpval ; one to work on
- int DOS
-
- ; set registers to something neat
-
- cli ; avoid interrupts here
- mov bx,offset newpval
- mov [bx].CR1,REG1_7201
- mov [bx].CR2A,REG2_7201
- mov [bx].CR3,REG3_7201
- mov [bx].CR4,REG4_7201
- mov [bx].CR5,REG5_7201
- mov bx,prthnd ; get handle
- mov ah,IOCTL
- mov al,IOwrite ; set new values
- int DOS
- opnprt2a:
- push es ; save this for a flash
- mov bx,SEG_7201
- mov es,bx
- mov bx,modem.mdstat
- mov byte ptr es:[bx],10H ; clear external/status interrupts
- mov byte ptr es:[bx],30H ; clear special receive cond. int.
- mov byte ptr es:[bx],38H ; set to end of interupt
- pop es ; back again
- sti ; interrupts are okay again
- ret
- OPNPRT endp
-
- ; Show the definition of a key. Since it isn't really necessary to redefine
- ; keys for the VICTOR/SIRIUS (assuming that KEYGEN is available), this isn't
- ; implemented, and the string returned to the calling sequence merely says so.
- ; Returns a string to print in AX, length of same in CX.
- ; Returns normally.
-
- SHOWKEY proc near
- mov ax,offset sh_key_str
- mov cx,sh_key_len
- ret
- SHOWKEY endp
-
- ; Clear the input buffer. This throws away all the characters in the
- ; serial interrupt buffer. This is particularly important when
- ; talking to servers, since NAKs can accumulate in the buffer.
- ; Returns normally.
-
- CLRBUF proc near
- cli
- mov ax,offset source
- mov srcpnt,ax
- mov count,0
- sti
- ret
- CLRBUF endp
-
- ; Clear to the end of the current line. Returns normally.
-
- CLEARL proc near
- mov dx,offset clreol
- mov ah,PRSTR
- int DOS
- ret
- CLEARL endp
-
- ; Put the char in AH to the serial port. This assumes the
- ; port has been initialized. Skip returns on success, returns ret if the
- ; character cannot be written.
- ; Add entry point OUTCH2 for non-flow controlled sending to
- ; prevent confusion of flow control logic at top of outchr; used by receiver
- ; buffer high/low water mark flow control code. [jrd]
-
- OUTCHR proc near
- cmp flowoff,0 ; Are we doing flow control.
- je outch2 ; No, just continue.
- cmp ah,flowoff ; sending xoff?
- jne outch1 ; ne = no
- mov xofsnt,usron ; indicate user level xoff being sent
- jmp outch1b
- outch1: cmp ah,flowon ; user sending xon?
- jne outch1b ; ne = no
- mov xofsnt,off ; say an xon has been sent (cancels xoff)
- outch1b:cmp xofrcv,off ; Are we being held (xoff received)?
- je outch2 ; e = no - it's OK to go on.
- cmp flags.timflg,0 ; is timer off?
- je outch2 ; e = yes, no timeout period
- push cx ; save reg
- mov ch,trans.rtime ; receive timeout interval (sec)
- mov cl,0 ; convert to 4 millsec increments
- jcxz outch1c ; z = no timeout wanted.
-
- outch1a:cmp xofrcv,off ; Are we being held (xoff received)?
- je outch1c ; e = no - it's OK to go on.
- push ax
- mov ax,4 ; 4 millisec wait loop
- call pcwait
- pop ax
- loop outch1a ; and try it again
- mov xofrcv,off ; timed out, force it off and fall thru
- outch1c:pop cx ; end of flow control section
- ; OUTCH2 is entry point for sending without flow control
- OUTCH2: mov al,ah ; Parity routine works on AL.
- call dopar ; Set parity appropriately.
- mov ah,al ; Don't overwrite character with status
- push bx
- push cx
- push es
- xor cx,cx
- mov bx,SEG_7201 ; point at 7201
- mov es,bx
- mov bx,modem.mdstat
- outch3:
- mov al,es:[bx]
- test al,4 ; ready?
- jnz outch4 ; yes
- loop outch3
- jmp outch5 ; Timeout
- outch4:
- mov al,ah ; Now send it out
- mov bx,modem.mddat
- mov es:[bx],al
- pop es
- pop cx
- pop bx
- ret
- outch5:
- pop es
- pop cx
- pop bx
- ret
- OUTCHR endp
-
- ; This routine blanks the screen. Returns normally.
-
- CMBLNK proc near
- mov dx,offset clrscr
- mov ah,PRSTR
- int DOS
- ret
- CMBLNK endp
-
- ; Locate: homes the cursor. Returns normally.
-
- LOCATE proc near
- mov dx,offset home
- mov ah,PRSTR
- int DOS
- ret
- LOCATE endp
-
- ; write a line in inverse video at the bottom of the screen...
- ; the line is passed in dx, terminated by a dollar sign. Returns normally.
-
- PUTMOD proc near
- push si ; better save this
- push dx ; preserve message
- mov dx,offset start_25 ; to set up for write to 25
- mov ah,PRSTR
- int DOS
- mov ah,DCONIO ; output a char at a time
- pop si ; get back message
- cld ; better increment
- putmod1:
- lodsb ; get byte
- cmp al,'$' ; is it end of string?
- je putmod2
- mov dl,al
- int DOS
- jmp putmod1
- putmod2:
- mov dx,offset end_25 ; back to normal
- mov ah,PRSTR
- int DOS
- pop si ; and restore it
- ret
- PUTMOD endp
-
- ; clear the mode line written by putmod. Returns normally.
-
- CLRMOD proc near
- mov dx,offset clr_25 ; to clear line 25
- mov ah,PRSTR
- int DOS
- ret
- CLRMOD endp
-
- ; put a help message on the screen. This one uses reverse video...
- ; pass the message in ax, terminated by a null. Returns normally.
-
- PUTHLP proc near
- push si
- mov si,ax
- mov ah,DCONIO ; don't check anything...
- cld ; better increment on strings
- puthlp1:
- lodsb ; get byte
- cmp al,0 ; is it null (null-terminated string)
- je puthlp2
- mov dl,al
- int DOS
- jmp puthlp1
- puthlp2:
- mov dl,13 ; want a crlf
- int DOS
- mov dl,10
- int DOS
- pop si
- ret
- PUTHLP endp
-
- ; Set the baud rate for the current port, based on the value
- ; in the portinfo structure. Returns carry clear.
-
- BAUDST PROC NEAR
- mov dx,offset bdtab ; baud rate table, ascii
- xor bx,bx ; help is the table itself
- mov ah,cmkey ; get keyword
- call comnd
- jc baudst1 ; c = failure
- push bx ; save result
- mov ah,cmeol ; get confirmation
- call comnd
- pop bx
- jc baudst1 ; c = failure
- mov si,portval
- mov ax,[si].baud ; remember original value
- mov [si].baud,bx ; set the baud rate
- call dobaud ; use common code
- clc
- baudst1:ret
- BAUDST ENDP
- ; Set the baud rate for the current port, based on the value
- ; in the portinfo structure. Returns normally. Method of setting using
- ; IOCTL thanks to Andreas Stumpf
-
- DOBAUD proc near
- push ax ; these too [jrd]
- push bx
- push cx
- push dx
- mov bx,portval
- mov bx,[bx].baud
- cmp bx,0
- jl unk_baud ; out of range
- cmp bl,bdtab ; number of table entries
- jge unk_baud ; out of range
- shl bx,1 ; get index into table
- mov ax,offset bddat ; start of table
- add bx,ax
- mov ax,[bx] ; get divider
- cmp ax,0FFH ; unimplemented baud rate?
- je unk_baud ; that's right
- mov bx,offset newpval
- mov [bx].baudr,ax ; set it in structure no matter what [bgp]
- cmp prthnd,0 ; anything open?
- jge dobaud0 ; yes, do it nice
- push es ; better save this...
- push ax ; save divider
- mov bx,SEG_8253 ; point at timer
- mov es,bx
- mov bx,CTRL_8253 ; set up function first
- mov ax,modem.mdcom ; set up control byte
- ror al,1 ; need port number in high bits
- ror al,1
- and al,0C0H ; keep only top 2 bits
- add al,36H ; set both, Mode 3, binary
- mov es:[bx],al
- mov bx,modem.mdcom ; Where to write the rate
- pop ax ; get divider back
- mov es:[bx],al
- mov es:[bx],ah ; done
- pop es
- jmp dobaud1
- dobaud0: ; [bgp]
- mov ah,IOCTL
- mov al,IOwrite
- mov bx,prthnd ; set the poor thing
- mov cx,plength
- mov dx,offset newpval
- int DOS
- dobaud1:
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- unk_baud:
- mov ah,PRSTR
- mov dx,offset badbd ; Give an error message.
- int DOS
- pop dx ; restore regs [jrd]
- pop cx
- pop bx
- pop ax
- ret
- DOBAUD endp
-
- ; Get the current baud rate from the serial card and set it
- ; in the portinfo structure for the current port. Returns normally.
- ; This is used during initialization. The method of getting the baud
- ; rate directly from the port handler is thanks to Andreas Stumpf.
- ; Note that this assumes that the thing has a defined baud rate to
- ; start with from the initialization and the opnprt has been called on
- ; the current port so that the values in newpval are defined.
-
- GETBAUD proc near
- push ax
- push bx
- push cx
- push dx
- cmp prthnd,0 ; opened?
- jne go_gb ; yes, get the rate
- call opnprt ; no, open it
- go_gb:
- mov bx,offset newpval
- mov ax,[bx].baudr
- xor ch,ch
- mov cl,bdtab ; entries in baudtable
- mov bx,offset bddat-2
- add bx,cx
- add bx,cx
- loop_gb:
- cmp ax,[bx]
- je have_gb
- dec bx
- dec bx
- dec cx
- jnz loop_gb
- have_gb:
- dec cx ; value is one greater than desired
- mov bx,portval ; cx=-1 means unrecognized (dropped off bottom)
- mov [bx].baud,cx
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- GETBAUD endp
-
- ; Skip returns if no character available at port,
- ; otherwise returns with char in al, # of chars in buffer in dx.
- ; Revised 22 May 1986, and again slightly 2 August 1986 by [jrd]
- ; Direct copy from msxibm.asm [jrd]
-
- PRTCHR proc near
- call chkxon ; see if we need to xon
- cmp count,0 ; any characters available?
- jnz prtch1 ; nz = yes, get one
- xor dx,dx ; return count of zero
- stc
- ret ; No data
- prtch1:
- push si ; save si
- cli ; interrupts off, to keep srcpnt & count consistent
- mov si,srcpnt ; address of next available slot in buffer
- sub si,count ; minus number of unread chars in buffer
- cmp si,offset source ; located before start of buffer (wrapped)?
- jae prtch2 ; ae = no
- add si,BUFSIZ ; else do arithmetic module bufsiz
- prtch2:
- mov al,byte ptr [si] ; get a character into si
- dec count ; one less unread char now
- sti ; interrupts back on now.
- pop si
- mov dx,count ; return # of chars in bufer
- clc
- ret
- PRTCHR endp
-
- ; Examine incoming communications stream for a packet SOP character.
- ; Return CX= count of bytes starting at the SOP character (includes SOP)
- ; and carry clear. Return CX = 0 and carry set if SOP is not present.
- ; Destroys AL.
- peekcom proc far
- mov cx,count ; qty in circular buffer
- cmp cx,6 ; basic NAK
- jb peekc4 ; b = two few chars, get more
- push bx
- cli ; interrupts off, to keep srcpnt & count consistent
- mov bx,srcpnt ; address of next available slot in buffer
- sub bx,cx ; minus number of unread chars in buffer
- cmp bx,offset source ; located before start of buf?
- jae peekc1 ; ae = no
- add bx,bufsiz ; else do arithmetic modulo bufsiz
- peekc1: mov al,[bx]
- cmp al,trans.rsoh ; packet receive SOP?
- je peekc3 ; e = yes
- inc bx
- cmp bx,offset source+bufsiz ; beyond end of buffer?
- jb peekc2 ; b = no
- mov bx,offset source ; wrap around
- peekc2: loop peekc1 ; keep looking
- sti
- pop bx
- stc ; set carry for no SOP
- ret
- peekc3: sti ; interrupts back on now
- pop bx
- inc cx ; include SOP in count
- clc ; say SOP found
- ret ; CX has count remaining
-
- peekc4: xor cx,cx ; return count of zero
- stc ; say no data
- ret
- peekcom endp
-
- ; local routine to see if we have to transmit an xon
- chkxon proc near
- cmp flowon,0 ; doing flow control?
- je chkxo1 ; no, skip all this
- test xofsnt,usron ; did user send an xoff?
- jnz chkxo1 ; nz = yes, don't contradict it here
- test xofsnt,bufon ; have we sent a buffer level xoff?
- jz chkxo1 ; z = no, forget it
- cmp count,mntrgl ; below (low water mark) trigger?
- jae chkxo1 ; no, forget it
- mov ah,flowon ; ah gets xon
- and xofsnt,off ; remember we've sent the xon.
- call outch2 ; send via non-flow controlled entry point
- chkxo1: ret
- chkxon endp
-
- ; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the
- ; cycle of clear input buffer, wait 1 second, test if buffer empty then exit
- ; else repeat cycle. Requires that the port be initialized before hand.
- ; Ihosts is used by the local send-file routine just after initializing
- ; the serial port.
- ; 22 March 1986 [jrd]
- ; 30 July 1986 Avoid sending nulls if no flow control [bgp]
-
- IHOSTS proc near
- push ax ; save the registers
- push cx
- push dx
- mov xofrcv,off ; clear old xoff received flag
- mov xofsnt,off ; and old xoff sent flag
- mov ah,flowon ; put Go-ahead flow control char in ah
- or ah,ah ; check for null char
- jz ihosts1 ; z=null, don't send it
- call outchr ; send it (release Host's output queue)
- ihosts1:call clrbuf ; clear out interrupt buffer
- pop dx ; empty buffer. we are done here.
- pop cx
- pop ax
- ret
- IHOSTS endp
-
- ; IHOSTR - initialize the remote host for our reception of a file by
- ; sending the flow-on character (XON typically) to release any held
- ; data. Called by receive-file code just after initializing the serial
- ; port. 22 March 1986 [jrd]
- ; 30 July 1986 Avoid sending null if no flow control [bgp]
-
- IHOSTR proc near
- push ax ; save reg
- mov xofrcv,off ; clear old xoff received flag
- mov xofsnt,off ; and old xoff sent flag
- mov ah,flowon ; put Go-ahead flow control char in ah
- or ah,ah ; check for null char
- jz ihostr1 ; z=null, don't send it
- call outchr ; send it (release Host's output queue)
- ihostr1:pop ax
- ret
- IHOSTR endp
-
- ; Global proc to hang up the phone by making DTR and RTS low.
-
- DTRLOW proc near
- mov ah,cmline ; allow text to be able to display help
- mov bx,offset rdbuf ; dummy buffer
- mov dx,offset hnghlp ; help message
- call comnd ; get a confirm
- jnc dtrlow1 ; nc = success
- ret ; carry set = failure
- dtrlow1:call serhng ; drop DTR and RTS
- mov ah,PRSTR ; give a nice message
- mov dx,offset hngmsg
- int dos
- clc
- ret
- DTRLOW endp
-
- ; SERHNG us used to hang up the phone. This resets the port (by calling
- ; serrst), and then forces DTR and RTS low to terminate the connection.
- ; 12 April 1986 [bgp]
- ; 30 July 1986 Turn them back on again after 3 seconds so new connection can
- ; be made [bgp]
-
- SERHNG proc near
- call serrst ; reset the port to be sure
- push dx
- push cx
- push bx
- push ax
- cmp prthnd,0 ; nice method open? [bgp]
- jge serhng0 ; yes
- push es ; better save this
- mov bx,SEG_7201 ; point at controller
- mov es,bx
- mov bx,modem.mdstat
- cli ; no interrupts please
- mov byte ptr es:[bx],5 ; register 5
- mov byte ptr es:[bx],REG5_7201 and DTR_RTS_OFF
- sti ; interrupts ok again
- mov ax,3000 ; sleep for 3 seconds
- call pcwait
- mov bx,SEG_7201
- mov es,bx
- mov bx,modem.mdstat
- cli ; no interrupts please
- mov byte ptr es:[bx],5
- mov byte ptr es:[bx],REG5_7201
- sti ; interrupts ok again
- pop es
- jmp short serhng1 ; [bgp]
- serhng0:
- mov bx,offset newpval
- mov [bx].CR5,REG5_7201 and DTR_RTS_OFF
- mov dx,bx ; where the stuff is
- mov cx,plength ; how long it is
- mov bx,prthnd ; get handle
- mov ah,IOCTL
- mov al,IOwrite ; set new values
- int DOS
- mov ax,3000 ; sleep for 3 seconds
- call pcwait
- mov bx,offset newpval ; turn them back on again...
- mov [bx].CR5,REG5_7201
- mov dx,bx
- mov cx,plength
- mov bx,prthnd
- mov ah,IOCTL
- mov al,IOwrite
- int DOS
- serhng1:
- pop ax
- pop bx
- pop cx
- pop dx
- ret
- SERHNG endp
-
- ; SHOW MODEM, displays current status of lines DSR, CD, and CTS.
- ; Uses global byte mdmhand, the modem line status register. [jrd]
-
- SHOMODEM proc near
- mov ah,cmeol
- call comnd
- jc shomodem4 ; c = failure
- mov dx,offset shmdm0 ; assume DSR is not set
- test mdmhand,20h ; is bit set?
- jnz shomodem1 ; z = no
- mov dx,offset shmdm1 ; DSR is asserted (line active)
- shomodem1:
- mov ah,PRSTR
- int DOS
- test mdmhand,80h ; test for CD
- jz shomodem2 ; z = off
- mov dx,offset shmdm3 ; actually have CD
- shomodem2:
- int DOS
- mov dx,offset shmdm4 ; assume no CTS
- test mdmhand,10H ; test for CTS
- jz shomodem3
- mov dx,offset shmdm5 ; actually have CTS
- shomodem3:
- int DOS
- clc
- shomodem4:ret
- SHOMODEM endp
-
-
- ; Get modem status and set global byte mdmhand. Preserve all registers.
-
- ; Check the status of the return control lines from the serial port.
- ; Since this function doesn't care if the port has been properly
- ; initialized or anything else we will always go directly to the
- ; hardware. This is actually quite reasonable since the values
- ; returned in IOCTL from earlier will have no relation to the current
- ; state of reality. [bgp]
- ; Note that the method of getting DSR is a little weird. There are
- ; no connections on the 7201 for DSR so we have to get it from one
- ; of the 6522s where there are a few free lines (specifically, the
- ; one that controls the keyboard interface and the CRT brightness/
- ; contrast. This one is at E8040-E804F with line PA3 for DSRA and
- ; PA5 for DSRB. Note that a zero is registered for an active line
- ; on the DSR sense.
-
- getmodem proc near ; gets modem status upon request
- mov mdmhand,0 ; assume nothing is on
- push bx
- push es ; better save these
- mov bx,0E804H ; segment of 6522
- mov es,bx
- mov bl,8 ; assume looking at port A
- cmp flags.comflg,1
- je getmod1 ; e = it is A
- mov bl,20H ; actually looking at B
- getmod1:test es:[1],bl ; is DSR bit set?
- jnz getmod2 ; nz = no
- or mdmhand,20h ; DSR is asserted (line active)
- getmod2:mov bx,SEG_7201 ; point at 7201
- mov es,bx
- mov bx,modem.mdstat
- test byte ptr es:[bx],8 ; test for CD
- jz getmod3 ; z = off
- or mdmhand,80h ; actually have CD
- getmod3:test byte ptr es:[bx],20H ; test for CTS
- jz getmodx ; z = off
- or mdmhand,10h ; actually have CTS
- getmodx:pop es
- pop bx
- getmodem endp
-
- ; Send a break out the current serial port. Returns normally.
- ; Changed to use IOCTL function 12 April 1986 [bgp]
- ; 30 July 1986 Direct to hardware if not opened right [bgp]
-
- SENDBR proc near
- push es
- push dx
- push cx
- push bx
- push ax
- mov ax,250 ; break length in msec
- push ax ; for later use
- jmp sendbrz
-
- sendbl:
- push es
- push dx
- push cx
- push bx
- push ax
- mov ax,3500 ; break length in msec
- push ax ; for later use
- sendbrz:
- cmp prthnd,0 ; open ok? [bgp]
- jge sendbr0 ; yes, do it nice
- mov bx,SEG_7201 ; point at 7201
- mov es,bx
- mov bx,modem.mdstat
- cli ; no interrupts please
- mov byte ptr es:[bx],1 ; register 1
- mov byte ptr es:[bx],REG1_7201
- mov byte ptr es:[bx],5
- mov byte ptr es:[bx],REG5_7201 or BREAK_ON
- sti ; interrupts ok again
- pop ax
- call wait_msec
- cli ; no interrupts
- mov byte ptr es:[bx],5
- mov byte ptr es:[bx],REG5_7201
- mov byte ptr es:[bx],1
- mov byte ptr es:[bx],REG1_7201 or ENABLE_INT
- sti ; interrupts ok again
- jmp sendbr1 ; [bgp]
- sendbr0:
- mov bx,offset newpval
- mov [bx].CR1,REG1_7201 ; to disable interrupts
- mov [bx].CR5,REG5_7201 or BREAK_ON
- mov dx,bx ; where the stuff is
- mov cx,plength ; how much there is
- mov bx,prthnd ; get handle
- mov ah,IOCTL
- mov al,IOwrite ; set new values
- cli ; avoid interrupts here
- int DOS
- mov bx,SEG_7201 ; have to explicitly do register 1
- mov es,bx ; IOCTL doesn't seem to touch it
- mov bx,modem.mdstat
- mov byte ptr es:[bx],1 ; Register 1
- mov byte ptr es:[bx],REG1_7201
- sti ; interrupts back on
- pop ax
- call wait_msec ; kill time
- mov bx,offset newpval
- mov [bx].CR5,REG5_7201
- mov bx,prthnd
- mov ah,IOCTL
- mov al,IOwrite
- cli ; no interrupts please
- int DOS
- mov bx,SEG_7201 ; Point at 7201 serial controller
- mov es,bx
- mov bx,modem.mdstat
- mov byte ptr es:[bx],1 ; Register 1 must be done explicitly
- mov byte ptr es:[bx],REG1_7201 or ENABLE_INT
- sti ; interrupts are okay again
- sendbr1:
- pop ax
- pop bx
- pop cx
- pop dx
- pop es
- clc ; need to stay connected
- ret ; And return.
- SENDBR endp
-
- ; Wait for the # of milliseconds in ax. The delay is set for a 5 MHz
- ; clock rate. Actual delay for ax=1 is 1.007 msec, plus 1.005 msec
- ; for each increment in ax.
-
- WAIT_MSEC proc near
- pcwait: ; entry point for the outside world...
- push cx ; 10 cycles
- mov cx,ax ; 2 cycles
- wait_msec1:
- push cx ; 10 cycles
- mov cx,294 ; 4 cycles
- wait_msec2:
- loop wait_msec2 ; 5+17*(CX-1) cycles
- pop cx ; 8 cycles
- loop wait_msec1 ; 17 cycles if jump, 5 cycles if no jump
- pop cx ; 8 cycles
- ret
- WAIT_MSEC endp
-
- ; Position the cursor according to contents of DX:
- ; DH contains row, DL contains column. Returns normally.
-
- POSCUR proc near
- push ax
- push dx ; save this
- mov dx,offset mov_pfx ; move prefix string
- mov ah,PRSTR
- int DOS
- pop dx
- push dx
- mov dl,dh
- add dl,' ' ; this is the row
- mov ah,DCONIO ; no checking please
- int DOS
- pop dx
- push dx
- add dl,' ' ; this is the column
- int DOS
- pop dx
- pop ax
- ret
- POSCUR endp
-
- ; Delete a character from the terminal. This works by printing
- ; backspaces and spaces. Returns normally.
-
- DODEL proc near
- mov dx,offset delstr ; Erase character.
- mov ah,PRSTR
- int DOS
- ret
- DODEL endp
-
- ; Move the cursor to the left margin, then clear to end of line.
- ; Returns normally.
-
- CTLU proc near
- mov dx,offset clrlin
- mov ah,PRSTR
- int DOS
- ret
- CTLU endp
-
- ; set the current port.
-
- COMS proc near
- mov dx,offset comptab
- mov bx,0
- mov ah,CMKEY
- call comnd
- jnc coms1 ; nc = success
- ret
- coms1: push bx
- mov ah,cmeol
- call comnd ; Get a confirm
- pop bx
- jnc coms2
- ret
- coms2: call serrst ; reset current port
- mov flags.comflg,bl ; Set the comm port flag.
- cmp flags.comflg,1 ; Using Com 1?
- jne coms0 ; Nope.
- mov ax,offset port1
- mov portval,ax
- mov modem.mddat,DATAA_7201 ; Set COM1 defaults.
- mov modem.mdstat,STATA_7201
- mov modem.mdcom,SETA_8253
- call opnprt ; open the handle
- ret
- coms0:
- mov ax,offset port2
- mov portval,ax
- mov modem.mddat,DATAB_7201 ; Set COM2 defaults.
- mov modem.mdstat,STATB_7201
- mov modem.mdcom,SETB_8253
- call opnprt
- ret
- COMS endp
-
- ; initialization for using serial port. This routine performs
- ; any initialization necessary for using the serial port, including
- ; setting up interrupt routines, setting buffer pointers, etc.
- ; Doing this twice in a row should be harmless (this version checks
- ; a flag and returns if initialization has already been done).
- ; SERRST below should restore any interrupt vectors that this changes.
- ; Returns normally. Modified to IOCTL function 12 April 1986 [bgp]
-
- SERINI proc near
- push es
- push dx
- push cx
- push bx
- push ax
- cmp portin,FALSE ; Did we initialize port already?
- je serin0
- jmp serin2 ; Yes, just leave
- serin0:
- cli ; Disable interrupts
- xor ax,ax ; Address low memory
- mov es,ax
- mov bx,modem.mdintv
- mov ax,es:[bx]
- mov savsci,ax
- mov ax,offset serint ; Point at our routine
- mov es:[bx],ax
- add bx,2 ; Now for CS value
- mov ax,es:[bx]
- mov savscs,ax
- mov es:[bx],cs
- mov portin,1 ; Note that we are initialized
- mov ax,offset source
- mov srcpnt,ax
- mov count,0
- mov ax,SEG_8259 ; Point at 8259 interrupt controller
- mov es,ax
- mov bx,CW2_8259 ; Control word 2
- mov al,es:[bx]
- and al,modem.mden ; Enable INT1 (all from 7201)
- mov es:[bx],al ; Save it
- mov bx,CW1_8259 ; Control word 1
- mov al,modem.mdmeoi ; Clear any outstanding requests
- mov es:[bx],al
-
- ; Note that access to the serial controller here is only to register 1 which
- ; must be done explicitly anyway, so there is no reason to care about
- ; whether a port is open [bgp]
-
- mov bx,SEG_7201 ; Point at 7201 serial controller
- mov es,bx
- mov bx,modem.mdstat
- mov byte ptr es:[bx],1 ; Register 1 must be done explicitly
- mov byte ptr es:[bx],REG1_7201 or ENABLE_INT
- mov byte ptr es:[bx],10H ; Clear external/status interrupts
- mov byte ptr es:[bx],30H ; Clear special receive cond. int.
- mov byte ptr es:[bx],38H ; Set to end of interrupt
- sti ; Allow interrupts
- mov bx,portval ; get port [jrd]
- mov parmsk,0FFH ; parity mask, assume parity is None. [jrd]
- cmp [bx].parflg,PARNON ; is it None?
- je serin1 ; e = yes
- mov parmsk,07FH ; no, pass lower 7 bits as data
- serin1:
- mov bx,[bx].flowc ; get flow control chars
- mov flowoff,bl ; xoff or null
- mov flowon,bh ; xon or null
- serin2: pop ax
- pop bx
- pop cx
- pop dx
- pop es
- clc ; carry clear for success
- ret
- SERINI endp
-
- ; Reset the serial port. This is the opposite of serini. Calling
- ; this twice without intervening calls to serini should be harmless.
- ; Returns normally. Modified to use IOCTL function 12 April 1986 [bgp]
- ; 30 July 1986 Make it go direct to hardware if handle open failed [bgp]
- ; Also, don't reset the port until the transmit buffer is empty
-
- SERRST proc near
- push es ; preserve this
- push dx
- push cx
- push bx
- push ax
- cmp portin,FALSE ; Reset already?
- je srst0 ; Yes, just leave.
- mov bx,SEG_7201 ; point at 7201 [bgp]
- mov es,bx
- mov bx,modem.mdstat
- sersta:
- cli
- mov byte ptr es:[bx],1 ; want status register 1
- mov al,es:[bx] ; get status
- sti
- test al,1 ; all sent? (transmitter and shift reg. empty)
- jz sersta ; no, wait...
- cli ; Disable interrupts
- mov bx,SEG_8259 ; Point at 8259 interrupt controller
- mov es,bx
- mov bx,CW2_8259
- mov al,es:[bx]
- or al,modem.mddis ; Turn off INT1
- mov es:[bx],al
- xor bx,bx ; Address low memory
- mov es,bx
- mov bx,modem.mdintv ; Restore the serial card int vector
- mov ax,savsci
- mov es:[bx],ax
- add bx,2 ; Restore CS too.
- mov ax,savscs
- mov es:[bx],ax
-
- ; As in SERINI, the only access to the serial controller is to register 1
- ; which must be done explicitly anyway, so we don't care about the handle [bgp]
-
- mov bx,SEG_7201 ; Point at 7201 serial controller
- mov es,bx
- mov bx,modem.mdstat
- mov byte ptr es:[bx],1 ; Register 1 has to be done explicitly
- mov byte ptr es:[bx],REG1_7201
- mov portin,FALSE ; Reset flag.
- sti
- srst0:
- pop ax
- pop bx
- pop cx
- pop dx
- pop es ; All done.
- ret ; All done.
- SERRST endp
-
- ; serial port interrupt routine. This is not accessible outside this
- ; module, handles serial port receiver interrupts.
- ; Revised on 22 May 1986, again 2 August 1986 to run at 38.4kb on PC's. [jrd]
- ; Srcpnt holds offset, within buffer Source, where next rcv'd char goes.
- ; Count is number of chars now in buffer, and oldest char is srcpnt-count
- ; done modulo size of Source. All pointer management is handled here.
- ; Control-G char substituted for char(s) lost in overrun condition. [jrd]
- ; Adapted from msxibm.asm code. [jrd]
- ; Fixed test for receiver overrun. [bgp]
-
- SERINT proc near
- push ax ; [jrd]
- push ds ; do ds and ax first [jrd]
- push es
- push bx
- push dx
- mov ax,seg data
- mov ds,ax ; address data segment
- mov bx,SEG_7201 ; point at 7201
- mov es,bx
- mov bx,modem.mdstat
- mov al,es:[bx] ; get status (register 0)
- mov byte ptr es:[bx],1 ; want status register 1 [bgp]
- mov ah,es:[bx] ; get status [bgp]
- mov bx,STATA_7201 ; this one is always channel A
- mov byte ptr es:[bx],38H ; Notify 7201 of end of interrupt
- mov bx,SEG_8259 ; point at 8259
- mov es,bx
- mov bx,CW1_8259
- mov dl,modem.mdmeoi
- mov es:[bx],dl ; Clear interrupt
- test al,MDMINP ; anything there (status register 0)?
- jnz srint0 ; nz = yes
- jmp retint ; and exit now (common jump point)
- srint0:
- mov bx,SEG_7201
- mov es,bx
- and ah,MDMOVER ; select overrun bit (status register 1)[jrd]
- mov overrun,ah ; save it for later [jrd]
- jz srint0a ; no overrun
- mov bx,modem.mdstat
- mov byte ptr es:[bx],30H ; Clear overrun error status
- srint0a:
- mov bx,modem.mddat
- mov al,es:[bx] ; get data byte
- cmp flowoff,0 ; flow control active?
- je srint4 ; e = no
- mov ah,al ; ah = working copy. Check flow cntl.
- and ah,parmsk ; strip parity temporarily, if any. [jrd]
- cmp ah,flowoff ; acting on Xoff?
- jne srint3 ; ne = Nope, go on
- cmp xofsnt,0 ; have we sent an outstanding XOFF? [jrd]
- jne srint1 ; ne = yes, ignore (possible echo)
- mov xofrcv,bufon ; Set the flag saying XOFF received
- srint1: jmp retint ; and exit
- srint3:
- cmp ah,flowon ; acting on Xon?
- jne srint4 ; ne = Nope, go on
- mov xofrcv,off ; Clear the XOFF received flag.
- jmp retint ; and exit
- srint4:
- mov ah,overrun ; get overrun flag [jrd]
- or ah,ah ; overrun?
- jz srint5 ; z = no
- mov ah,al ; yes, save present char
- mov al,BELL ; insert control-G for missing character
- srint5:
- mov bx,srcpnt ; address of buffer storage slot
- mov byte ptr [bx],al ; store the new char in buffer "source"
- inc srcpnt ; point to next slot
- inc bx
- cmp bx,offset source+BUFSIZ ; beyond end of buffer?
- jb srint6 ; b = not past end
- mov srcpnt,offset source ; wrap buffer arount
- srint6:
- cmp count,BUFSIZ ; filled already?
- jae srint7 ; ae = yes
- inc count ; no, add a char
- srint7:
- or ah,ah ; anything in overrun storage?
- jz srint8 ; z = no
- mov al,ah ; recover any recent char from overrun
- xor ah,ah ; clear overrun storage
- jmp srint5 ; yes, go store real second char
- srint8:
- sti ; ok to allow interrupts now, not before
- cmp count,MNTRGH ; past the high trigger point?
- jbe retint ; be = no, we're within our limit
- test xofsnt,bufon ; Has an XOFF been sent by buffer control?
- jnz retint ; nz = Yes.
- mov al,flowoff ; get the flow off char (Xoff or null)
- or al,al ; don't send null chars
- jz retint ; z = null, nothing to send
- call dopar ; set parity appropriately.
- mov ah,al ; Don't overwrite character with status
- push cx ; save reg [jrd]
- xor cx,cx ; loop counter [jrd]
- mov bx,SEG_7201 ; point at 7201
- mov es,bx
- mov bx,modem.mdstat
- srint9:
- mov al,es:[bx]
- test al,4 ; ready?
- jnz srint10 ; yes
- loop srint9
- jmp srint11 ; Timeout
- srint10:
- mov al,ah ; now send it out
- mov bx,modem.mddat
- mov es:[bx],al
- mov xofsnt,bufon ; Remember we sent an XOFF at buffer level
- srint11:
- pop cx ; [jrd]
- retint:
- sti ; be sure that this made it on
- pop dx
- pop bx
- pop es
- pop ds
- pop ax ; [jrd]
- iret
- SERINT endp
-
- ; Produce a beep. Returns normally.
-
- BEEP proc near
- mov dl,BELL
- mov ah,DCONIO ; No checks, just do it
- int DOS
- ret
- BEEP endp
- CODE ends
- end
-